package com.quanyan.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.quanyan.common.http.HttpClientUtils;
import com.quanyan.common.utils.DateUtils;
import com.quanyan.common.utils.GsonUtils;
import com.quanyan.common.utils.StringUtil;
import com.quanyan.user.cache.MyRedisTemplate;
import com.quanyan.user.constants.UserConstants;
import com.quanyan.user.mapper.TbImDetailsMapper;
import com.quanyan.user.model.db.TbImDetails;
import com.quanyan.user.model.db.TbImDetailsExample;
import com.quanyan.user.model.vo.response.RespHuanxinEntity;
import com.quanyan.user.model.vo.response.RespHuanxinErrorObj;
import com.quanyan.user.model.vo.response.RespHuanxinObj;
import com.quanyan.user.service.UserIMService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhang on 16/12/1.
 */
@Service
public class UserIMServiceImpl implements UserIMService {

    Logger logger = LoggerFactory.getLogger(UserIMServiceImpl.class);

    @Autowired
    private MyRedisTemplate myRedisTemplate;
    @Autowired
    private TbImDetailsMapper imDetailsMapper;

    /**环信地址*/
    @Value("${huanxin.url}")
    private String huanxinUrl;

    @Value("${huanxin.client.id}")
    private String huanxinClientId;

    @Value("${huanxin.client.secret}")
    private String huanxinClientSecret;

    @Value("${huanxin.nickname.prefix}")
    private String nicknamePrefix;

    /**
     * 获取环信Token
     * @param huanxinClientId
     * @param huanxinClientSecret
     * @return
     */
    @Override
    public String getHuanxinToken(String huanxinClientId, String huanxinClientSecret) {
        String huanxinToken = (String) myRedisTemplate.get(UserConstants.HUANXIN_TOKEN_KEY);
        if (huanxinToken == null) {
            Map param = new HashMap<>();
            param.put("grant_type", "client_credentials");
            param.put("client_id", huanxinClientId);
            param.put("client_secret", huanxinClientSecret);
            String json = GsonUtils.toJson(param);
            logger.info("参数{}", json);
            try {
                String result = HttpClientUtils.postJson(huanxinUrl + "/token", json);
                if (result != null) {
                    JSONObject resultJson = JSON.parseObject(result);
                    huanxinToken = resultJson.getString("access_token");
                    Integer tokenExpires = resultJson.getInteger("expires_in");
                    if (tokenExpires > 1000) {
                        myRedisTemplate.setByExpireSeconds(UserConstants.HUANXIN_TOKEN_KEY, huanxinToken, tokenExpires - 1000); // TODO 缓存时间暂定
                    }
                }
            } catch (Exception e) {
                logger.error("获取环信token失败!异常信息是：{}；时间是：{}", e.getMessage(), DateUtils.getStandardCurrentTime());
            }
        }
        return huanxinToken;
    }

    /**
     * 注册环信账号
     *
     * @param userName 环信用户名
     *                 使用英文字母和（或）数字的组合
     *                 不能使用中文
     *                 不能使用 email 地址
     *                 不能使用 UUID
     *                 用户ID的长度在1k字节以内
     *                 中间不能有空格或者井号（#）等特殊字符
     *                 允许的用户名正则 “[a-zA-Z0-9_-.]*”（a~z大小写字母/数字/下划线/横线/英文句号），其他都不允许 如果是大写字母会自动转成小写
     *                 不区分大小写。系统忽略大小写，认为 AA、Aa、aa、aA 都是一样的。如果系统已经存在了环信 ID 为 AA 的用户，再试图使用 aa 作为环信 ID 注册新用户，系统返回用户名重复，以此类推。
     *                 但是请注意：环信 ID 在数据上的表现形式还是用户最初注册的形式，注册时候使用的大写就保存大写，是小写就保存小写。即：使用 AA 注册，环信保存的 ID 就是 AA；使用 Aa 注册，环信保存的 ID 就是 Aa，以此类推。
     * @param password 环信密码
     */
    @Async
    @Override
    public void registerHuanxinUser(String userName, String password,Integer uid) {
        String huanxinToken = this.getHuanxinToken(huanxinClientId, huanxinClientSecret);
        //重试
        if (StringUtil.isBlankOrNull(huanxinToken)) {
            for (int i=0; i<3; i++) {
                huanxinToken = this.getHuanxinToken(huanxinClientId, huanxinClientSecret);
                if (StringUtil.isNotBlank(huanxinToken)) {
                    break;
                }
            }
        }
        //构造请求参数
        Map param = new HashMap<>();
        param.put("username", userName);
        param.put("password", password);
        String json = GsonUtils.toJson(param);
        logger.info("用户ID为：【{}】的请求参数{}", uid, json);
        //请求头参数
        Map headMap = new HashMap<>();
        headMap.put("Authorization", "Bearer " + huanxinToken);
        Map map ;
        String result = "";
        try {
            map = HttpClientUtils.postJsonResponse(huanxinUrl + "/users", json, headMap);
            result = (String) map.get("result");
            if (map.get("status") != null && (int) map.get("status") == 200) {
                RespHuanxinObj respHuanxinObj = JSON.parseObject(result,RespHuanxinObj.class);
                updateImDetails(uid,respHuanxinObj.getEntities().get(0).getUuid());
            } else if (map.get("status") != null && (int) map.get("status") == 401) {
                RespHuanxinErrorObj respHuanxinErrorObj = JSON.parseObject(result,RespHuanxinErrorObj.class);
                updateImDetails(uid,respHuanxinErrorObj.getError());
            }
        } catch (Exception e) {
            logger.error("用户ID为：【{}】的用户的返回值为：{}；环信账号失败信息：{};错误时间为：{}",uid,result,e.getMessage(),DateUtils.getStandardCurrentTime());
        }
    }

    /**
     * 添加用户环信详情
     * @param huanxinNickName
     * @param password
     * @param uid
     * @return
     */
    @Override
    public TbImDetails addImDetails(String huanxinNickName,String password,Integer uid){
        TbImDetails imDetails = new TbImDetails();
        imDetails.setNickName(huanxinNickName);
        imDetails.setPassword(password);
        imDetails.setUid(uid);
        imDetails.setCreateTime(DateUtils.getSecondTimestampOne(new Date()));
        imDetails.setUpdateTime(DateUtils.getSecondTimestampOne(new Date()));
        imDetailsMapper.insertSelective(imDetails);
        registerHuanxinUser(huanxinNickName,password,uid);
        return imDetails;
    }

    /**
     * 更新用户ImDetail详情
     * @param uid
     * @param uuid
     * @return
     */
    public int updateImDetails(Integer uid,String uuid){
        TbImDetailsExample example = new TbImDetailsExample();
        TbImDetailsExample.Criteria criteria = example.createCriteria();
        criteria.andUidEqualTo(uid);
        TbImDetails imDetails = new TbImDetails();
        imDetails.setUuid(uuid);
        imDetails.setUpdateTime(DateUtils.getSecondTimestampOne(new Date()));
        int n = imDetailsMapper.updateByExampleSelective(imDetails,example);
        return n;
    }
}
